/**
 * Copyright (c) 2017-2018, zengjintao (1913188966@qq.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jfast.framework.web.config;


import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import com.jfast.framework.bean.ClassFactory;
import com.jfast.framework.bean.JdkClassFactory;
import com.jfast.framework.exception.InitializationError;
import com.jfast.framework.kit.PropKit;
import com.jfast.framework.kit.StrKit;
import com.jfast.framework.log.Logger;
import com.jfast.framework.web.annotation.ConfigurationProperties;
import com.jfast.framework.orm.TypeConvert;

/**
 * JfastConfig 管理器
 * @author zengjintao
 * @version 1.0
 * @createTime 2017年11月14日下午4:06:43
 */
public class JfastConfigManager {

    public static PropKit DEFAULT_PROPKIT = null;
	
	private static final Logger logger = Logger.getLogger(JfastConfigManager.class);

	/**
	 * Jfast默认properties文件
	 */
	static {
		if (DEFAULT_PROPKIT == null) {
			DEFAULT_PROPKIT = new PropKit("jfast.properties");
		}
	}
	
	private static final ConcurrentHashMap<String, Object> configs = new ConcurrentHashMap<>();
	
	private static final ClassFactory classFactory = new JdkClassFactory();
	
	/**
	 * 实例化ConfigurationProperties注解的类
	 * @param beanClass
	 * @return
	 */
	public static <T> T createConfigBean(Class<T> beanClass){
		ConfigurationProperties configurationProperties = beanClass.getAnnotation(ConfigurationProperties.class);
		String location = configurationProperties.location();
		String prefix = configurationProperties.prefix();
		return createConfigBean(beanClass, prefix, location);
	}

	public static <T> T createConfigBean(Class<T> beanClass, String prefix) {
		return createConfigBean(beanClass, prefix, null);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T createConfigBean(Class<T> beanClass, String prefix,String propertiesFile) {
		
		PropKit propKit = null;
		if (StrKit.isNotEmpty(propertiesFile)) {
			propKit = new PropKit(propertiesFile);
		} else {
			propKit = DEFAULT_PROPKIT;
		}
		if (StrKit.isEmpty(prefix))
			throw new InitializationError("prefix can not be null");
		T object = (T) configs.get(beanClass.getName() + prefix);
		
		if (object != null) {
			return object;
		}
	    object = classFactory.createBean(beanClass);
		for (Method method : beanClass.getMethods()) {
			if (method.getName().startsWith("set")) {
				try {
					String key = StrKit.toLowerCaseFirst(method.getName().substring(3));
					String value = propKit.get(prefix.trim() + "." + key);
					if (StrKit.isNotEmpty(value)) {
						method.invoke(object, TypeConvert.convert(method.getParameterTypes()[0], value));
					}
				} catch (Exception e) {
					logger.error("参数注入异常",e);
				}
			}
		}
		configs.put(beanClass.getName() + prefix, object);
		return (T) object;
	}
}
